// =============================================================
// CFactory/CService/CServiceProxy/CServiceContainer
// ---------------------------------------
// Author : Woo-Hyun Kim
// Email : woorung@icu.ac.kr or woorung@nhncorp.com
// Date : Aug. 24, 2007
//
// # This is based on one of gSOAP examples, varparam
//   However, it is re-written for memory management.
// =============================================================
#include <iostream>

#include "env.h"
#include "base.nsmap"

using namespace std;
using namespace base; 

//------------------------------------------------------------------
// CObject
//------------------------------------------------------------------
cube__CObject::cube__CObject()
{
	this->soap = NULL;
}

/*
cube__CObject::cube__CObject(const cube__CObject &rhs)
{
	clone();
}
*/

cube__CObject::~cube__CObject()
{
	soap_unlink(this->soap, this);
}

/*
cube__CObject *cube__CObject::clone() const
{
	cout << "######### [clone] must be never called" << endl;

	return NULL;
}

cube__CObject &cube__CObject::operator=(const cube__CObject &rhs) 
{
	if(this==&rhs) return *this;

	return *clone();
}
*/

//------------------------------------------------------------------
// CMessage
//------------------------------------------------------------------
cube__CMessage::cube__CMessage()
{
	message = NULL;
}

/*
cube__CMessage::cube__CMessage(const cube__CMessage &rhs)
{
	message = soap_strdup(soap, rhs.message);
}
*/

cube__CMessage::~cube__CMessage()
{
	if(this->soap&&message) soap_dealloc(this->soap, message);
	else if(!this->soap&&message) delete []message;
}

/*
cube__CMessage *cube__CMessage::clone() const
{
	cube__CMessage *cloned = soap_new_cube__CMessage(soap, -1);
	cloned->message = soap_strdup(soap, this->message);

	return cloned;
}

cube__CMessage &cube__CMessage::operator=(const cube__CMessage &rhs) 
{
	if(this==&rhs) return *this;

	return *clone();
}
*/

int cube__CMessage::set(char *msg)
{
	if(this->soap) {
		if(message!=NULL) soap_dealloc(this->soap, message);

		message = soap_strdup(this->soap, msg);
	}
	else if(!this->soap) {
		if(message!=NULL) delete []message;

		message = new char[strlen(msg)+1];
		strcpy(message, msg);
	}

        return strlen(message);
}

char *cube__CMessage::get()
{
	return (char *) message;
}

void cube__CMessage::print()
{
        cout << message << endl;
}




//------------------------------------------------------------------
// KeyValue 
//------------------------------------------------------------------
cube__CKeyValue::cube__CKeyValue()
{
	key = NULL;
	value = NULL;
}

cube__CKeyValue::~cube__CKeyValue()
{
	if(this->soap) {
		if(key!=NULL) soap_dealloc(this->soap, key);
		if(value!=NULL) soap_dealloc(this->soap, value);
	}
	else if(!this->soap) {
		if(key!=NULL) delete []key;
		if(value!=NULL) delete []value;
	}
}

void cube__CKeyValue::set(char *k, char *v)
{
	if(this->soap) {
		if(key!=NULL) soap_dealloc(this->soap, key);
		if(value!=NULL) soap_dealloc(this->soap, value);

		key = soap_strdup(this->soap, k);
		value = soap_strdup(this->soap, v);
	}
	else if(!this->soap) {
		if(key!=NULL) delete []key;
		if(value!=NULL) delete []value;

		key = new char[strlen(k)+1];
		strcpy(key, k);
		value = new char[strlen(v)+1];
		strcpy(value, v);
	}
}

void cube__CKeyValue::setKey(char *k)
{
	if(this->soap) {
		if(key!=NULL) soap_dealloc(this->soap, key);

		key = soap_strdup(this->soap, k);
	}
	else if(!this->soap) {
		if(key!=NULL) delete []key;

		key = new char[strlen(k)+1];
		strcpy(key, k);
	}
}

void cube__CKeyValue::setValue(char *v)
{
	if(this->soap) {
		if(value!=NULL) soap_dealloc(this->soap, value);

		value = soap_strdup(this->soap, v);
	}
	else if(!this->soap) {
		if(value!=NULL) delete []value;

		value = new char[strlen(v)+1];
		strcpy(value, v);
	}
}

char *cube__CKeyValue::getKey()
{
	return key;
}

char *cube__CKeyValue::getValue()
{
	return value;
}

void cube__CKeyValue::print()
{
        cout << key << "=" << value << endl;
}



//------------------------------------------------------------------
// Service Info
//------------------------------------------------------------------
cube__CServiceInfo::cube__CServiceInfo()
{
	name = NULL;
	ip = NULL;
	port = -1;
	ttl = LONG_MAX;

	cpu = 0;
	load = 0;
}

cube__CServiceInfo::cube__CServiceInfo(char *__name, char *__ip, int __port, time_t __ttl)
{
	if(this->soap) {
		if(name!=NULL) soap_dealloc(this->soap, name);
		//if(iname!=NULL) soap_dealloc(this->soap, iname);
		if(ip!=NULL) soap_dealloc(this->soap, ip);

		name= soap_strdup(this->soap, __name);
		//iname= soap_strdup(this->soap, __name); // iname is the same as name
		ip= soap_strdup(this->soap, __ip);
	}
	else if(!this->soap) {
		if(name!=NULL) delete []name;
		//if(iname!=NULL) delete []iname;
		if(ip!=NULL) delete []ip;

		name= new char[strlen(__name)+1];
		strcpy(name, __name);
		//iname= new char[strlen(__name)+1]; // iname is the same as name
		//strcpy(iname, __name);
		ip = new char[strlen(__ip)+1];
		strcpy(ip, __ip);
	}

	port = __port;
	ttl = __ttl;

	cpu = 0;
	load = 0;
}

cube__CServiceInfo::~cube__CServiceInfo()
{
	if(this->soap) {
		if(name!=NULL) soap_dealloc(this->soap, name);
		//if(iname!=NULL) soap_dealloc(this->soap, iname);
		if(ip!=NULL) soap_dealloc(this->soap, ip);
	}
	else if(!this->soap) {
		if(name!=NULL) delete []name;
		//if(iname!=NULL) delete []iname;
		if(ip!=NULL) delete []ip;
	}
}

void cube__CServiceInfo::set(char *__name, char *__ip, int __port, time_t __ttl)
{
	if(this->soap) {
		if(name!=NULL) soap_dealloc(this->soap, name);
		//if(iname!=NULL) soap_dealloc(this->soap, iname);
		if(ip!=NULL) soap_dealloc(this->soap, ip);

		name= soap_strdup(this->soap, __name);
		//iname= soap_strdup(this->soap, __name); // iname is the same as name
		ip= soap_strdup(this->soap, __ip);
	}
	else if(!this->soap) {
		if(name!=NULL) delete []name;
		//if(iname!=NULL) delete []iname;
		if(ip!=NULL) delete []ip;

		name= new char[strlen(__name)+1];
		strcpy(name, __name);
		//iname= new char[strlen(__name)+1]; // iname is the same as name
		//strcpy(iname, __name);
		ip = new char[strlen(__ip)+1];
		strcpy(ip, __ip);
	}

	port = __port;
	ttl = __ttl;
}

void cube__CServiceInfo::setStatus(float cpu, float load)
{
	this->cpu = cpu;
	this->load = load;
}

void cube__CServiceInfo::setName(char *__name)
{
	if(this->soap) {
		if(name!=NULL) soap_dealloc(this->soap, name);
		//if(iname!=NULL) soap_dealloc(this->soap, iname);

		name= soap_strdup(this->soap, __name);
		//iname= soap_strdup(this->soap, __name);
	}
	else if(!this->soap) {
		if(name!=NULL) delete []name;
		//if(iname!=NULL) delete []iname;

		name= new char[strlen(__name)+1];
		strcpy(name, __name);

		//iname= new char[strlen(__name)+1];
		//strcpy(iname, __name);
	}
}

char *cube__CServiceInfo::getName()
{
	return name;
}

float cube__CServiceInfo::getCPU()
{
	return cpu;
}

float cube__CServiceInfo::getLoad()
{
	return load;
}

char *cube__CServiceInfo::getIP()
{
	return ip;
}

int cube__CServiceInfo::getPort()
{
	return port;
}

time_t cube__CServiceInfo::getTTL()
{
	return ttl;
}





//------------------------------------------------------------------
// Service 
//------------------------------------------------------------------
cube__CService::cube__CService()
{
	name = NULL;
	iname = NULL;
}

cube__CService::cube__CService(char *__name)
{
	if(this->soap) {
		if(name!=NULL) soap_dealloc(this->soap, name);

		name = soap_strdup(this->soap, __name);
		if(iname==NULL) iname = soap_strdup(this->soap, __name); // iname is the same as name
	}
	else if(!this->soap) {
		if(name!=NULL) delete []name;

		name = new char[strlen(__name)+1];
		strcpy(name, __name);

		if(iname==NULL) {
			iname = new char[strlen(__name)+1]; // iname is the same as name
			strcpy(iname, __name);
		}
	}
}

cube__CService::cube__CService(char *__name, char *__iname)
{
	if(this->soap) {
		if(name!=NULL) soap_dealloc(this->soap, name);
		if(iname!=NULL) soap_dealloc(this->soap, iname);

		name = soap_strdup(this->soap, __name);
		iname= soap_strdup(this->soap, __iname);
	}
	else if(!this->soap) {
		if(name!=NULL) delete []name;
		if(iname!=NULL) delete []iname;

		name= new char[strlen(__name)+1];
		strcpy(name, __name);
		iname= new char[strlen(__iname)+1];
		strcpy(iname, __iname);
	}
}

cube__CService::~cube__CService()
{
	if(this->soap) {
		if(name!=NULL) soap_dealloc(this->soap, name);
		if(iname!=NULL) soap_dealloc(this->soap, iname);
	}
	else if(!this->soap) {
		if(name!=NULL) delete []name;
		if(iname!=NULL) delete []iname;
	}
}

void cube__CService::set(char *__name)
{
	if(this->soap) {
		if(name!=NULL) soap_dealloc(this->soap, name);

		name= soap_strdup(this->soap, __name);
		if(iname==NULL) iname= soap_strdup(this->soap, __name); // iname is the same as name
	}
	else if(!this->soap) {
		if(name!=NULL) delete []name;

		name= new char[strlen(__name)+1];
		strcpy(name, __name);

		if(iname==NULL) {
			iname= new char[strlen(__name)+1]; // iname is the same as name
			strcpy(iname, __name);
		}
	}
}

void cube__CService::set(char *__name, char *__iname)
{
	if(this->soap) {
		if(name!=NULL) soap_dealloc(this->soap, name);
		if(iname!=NULL) soap_dealloc(this->soap, iname);

		name= soap_strdup(this->soap, __name);
		iname= soap_strdup(this->soap, __iname);
	}
	else if(!this->soap) {
		if(name!=NULL) delete []name;
		if(iname!=NULL) delete []iname;

		name= new char[strlen(__name)+1];
		strcpy(name, __name);
		iname= new char[strlen(__iname)+1];
		strcpy(iname, __iname);
	}
}

void cube__CService::service(char *__name)
{
	if(this->soap) {
		if(name!=NULL) soap_dealloc(this->soap, name);

		name= soap_strdup(this->soap, __name);
		if(iname==NULL) iname= soap_strdup(this->soap, __name);
	}
	else if(!this->soap) {
		if(name!=NULL) delete []name;

		name= new char[strlen(__name)+1];
		strcpy(name, __name);

		if(iname==NULL) {
			iname= new char[strlen(__name)+1];
			strcpy(iname, __name);
		}
	}
}

char *cube__CService::service()
{
	return name;
}

void cube__CService::instance(char *__iname)
{
	if(this->soap) {
		if(iname!=NULL) soap_dealloc(this->soap, iname);

		iname= soap_strdup(this->soap, __iname);
	}
	else if(!this->soap) {
		if(iname!=NULL) delete []iname;

		iname= new char[strlen(__iname)+1];
		strcpy(iname, __iname);
	}
}

char *cube__CService::instance()
{
	return iname;
}



//------------------------------------------------------------------
// Array
//------------------------------------------------------------------
CObjectArray::CObjectArray() : cube__CObject()
{
	__ptr = NULL;
	__size = 0;
	__offset = 0;
}

CObjectArray::CObjectArray(int n) : cube__CObject()
{
	grow(n);
}

CObjectArray::~CObjectArray()
{
	if(!this->soap&&__ptr) free(__ptr);
}

void CObjectArray::grow(int n)
{
	if(this->soap) __ptr = (cube__CObject **) soap_malloc(this->soap, n*sizeof(cube__CObject *));
	else __ptr = (cube__CObject **) malloc(n*sizeof(cube__CObject *));

	__size = n;
	__offset = 0;
}

cube__CObject *&CObjectArray::operator[](int i)
{
	if(i<0||i>=__size) {
		cout << "Error : out of range" << endl;
		exit(-1);
	}

	return __ptr[i-__offset];
}
